#include "ULUI_StatisticOut.h"
#include "UL_Global.h"
#include "ULGfx_History.h"
#include "ULGfx_Statistic.h"

#define STATISTIC_FINAL_START_X	100
#define STATISTIC_FINAL_START_Y	90

ULUI_StatisticOut ULUI_StatisticOut::statOut;

enum HistoryLookupIDs{
	SERIAL_NUMBER_BOX,
	DATE_BOX,
	RANGE_BOX,
	OK,
	EXIT	
};	

static char *menuTitles[] = {
	"                                ",
	"                                ",
	"                                ",
	"确定",
	"返回",
};

#define FIXED_GAP	20
#define SERIALS_PER_SCREEN	15
void ULUI_StatisticOut::Init()
{
	int i;
	ULUI_Menu menu;

	AttachEventHandler(this);

	pad.Reset();
	pad.EnableSolidBg(true);
	menu.SetFont(UL_Global::UnionLottoFont());
	pad.SetFont(UL_Global::UnionLottoFont());
	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		menu.SetID(i);
		menu.SetTitle(menuTitles[i]);
		menus.AddMenu(menu);
	}

	//Find menu's X is after tip
	menu.SetTitle("                                ");
	menu.GetTitleSize(tipWidth, tipHeight);
	menus.SetFirstMenuXY(VSDL_Point(STATISTIC_FINAL_START_X + tipWidth, STATISTIC_FINAL_START_Y + tipHeight));
	pad.SetStartXY(VSDL_Point(STATISTIC_FINAL_START_X + tipWidth * 2 + FIXED_GAP, STATISTIC_FINAL_START_Y));
	selectedBox = SERIAL_NUMBER_BOX;
	startSerialNo = 0;
	serialOffset = 0;
	nSerials = 0;
}

void ULUI_StatisticOut::CleanUp()
{
	pad.Reset();
	menus.Reset();
}

void ULUI_StatisticOut::Pause()
{
}

void ULUI_StatisticOut::Resume()
{
	selectedMenu = -1;
}

void ULUI_StatisticOut::Update(VSDL_GameEngine *game)
{
	char *str;
	ULG_History *ulgHistory = ULG_History::Instance();

	if (selectedMenu == -1){
		return ;
	}
	
	str = pad.GetString();

	switch (selectedMenu){
		case SERIAL_NUMBER_BOX:
			dateBoxString.clear();
			selectedBox = SERIAL_NUMBER_BOX;
			if (str != NULL){
				serialBoxString = str;
				startSerialNo = strtoul(str, NULL, 10);
			}
			break;
		case DATE_BOX:
			serialBoxString.clear();
			selectedBox = DATE_BOX;
			if (str != NULL){
				ULC_Serial *serial = ulgHistory->LookupSerial(str);
				dateBoxString = str;
				
				if (serial != NULL){
					startSerialNo = serial->sn; 
				}
			}
			break;
		case RANGE_BOX:
			if (str != NULL){
				rangeBoxString = str;
			}
			break;
		case OK:
			selectedMenu = -1;
			serialOffset = 0;
			readyToGo = false;

			ULC_Serial *serial;
			if (startSerialNo > 0 && rangeBoxString.length() > 0){
				nSerials = strtoul(rangeBoxString.c_str(), NULL, 10);
				if (nSerials <= 0){
					readyToGo = false;
					break;
				}

				//nSerials can be fixed to a correct value
				if (nSerials > SERIALS_PER_SCREEN){
					serial = ulgHistory->LookupRange(startSerialNo, nSerials);

					if (serial == NULL){
						readyToGo = false;
						break;
					}
					
					if (nSerials <= SERIALS_PER_SCREEN){
						nSerials = SERIALS_PER_SCREEN;	
						serial = ulgHistory->GetLatestSerials(nSerials);
						startSerialNo = serial->sn;
					}

				}else{
					int gap;

					serial = ulgHistory->LookupSerial(startSerialNo);

					if (serial == NULL){
						readyToGo= false;
						break;
					}

					gap = ulgHistory->CaculateGap(serial, ulgHistory->GetLatestSerial());

					if ((gap + 2) <= SERIALS_PER_SCREEN){

						nSerials = SERIALS_PER_SCREEN;	
						serial = ulgHistory->GetLatestSerials(nSerials);
						startSerialNo = serial->sn;
					}else{
						nSerials = SERIALS_PER_SCREEN;
					}
				}

				readyToGo = true;
			}

			break;
		case EXIT:
			game->PopState();
			break;
	}
}


void ULUI_StatisticOut::Draw(VSDL_GameEngine *game)
{
	char *str;
	VSDL_RGB rgbNormal(100, 100, 100);
	VSDL_RGB rgbSelected(250, 100, 100);
	VSDL_RGB rgb;
	VSDL_Point currentXY(STATISTIC_FINAL_START_X, STATISTIC_FINAL_START_Y);
	SDL_Surface *destSurf = game->GetSurface();
	ULG_Statistic *ulgStat = UL_Global::UnionLottoStatistic();
	ULG_History *ulgHistory = ULG_History::Instance();
	int serialNo;
	int historyY = STATISTIC_FINAL_START_Y + (EXIT + 2) * tipHeight;
	int totalSerials = nSerials;

	ulgStat->SetStartXY(VSDL_Point(STATISTIC_FINAL_START_X, historyY));

	UL_Global::UnionLottoShowBg();
	UL_Global::UnionLottoShowTitle();
	menus.Show(destSurf);
	//Draw static data background
	rgb.SetRGB(200, 200, 200);
	SPG_RectFilled(destSurf, STATISTIC_FINAL_START_X, historyY, destSurf->w, destSurf->h, rgb.GetRGB32(destSurf));
	//Show tips
	UL_Global::UnionLottoShowTip("输入任意一项进行查询,翻页使用PAGEUP和PAGEDOWN", currentXY);
	currentXY.y += tipHeight;
	UL_Global::UnionLottoShowTip("起始期号:(例:2012001)", currentXY);

	if (selectedBox == SERIAL_NUMBER_BOX){
		rgb = rgbSelected;
	}else{
		rgb = rgbNormal;
	}

	if (serialBoxString.length() > 0){
		UL_Global::UnionLottoShowTip(serialBoxString.c_str(), VSDL_Point(currentXY.x + tipWidth, currentXY.y));
	}

	SPG_Rect(destSurf, currentXY.x + tipWidth, currentXY.y, currentXY.x + tipWidth * 2, currentXY.y + tipHeight, rgb.GetRGB32(destSurf));

	rgb = rgbNormal;
	currentXY.y += tipHeight;

	UL_Global::UnionLottoShowTip("起始日期:(例:2012-01-01)", currentXY);

	if (selectedBox == DATE_BOX){
		rgb = rgbSelected;
	}else{
		rgb = rgbNormal;
	}

	if (dateBoxString.length() > 0){
		UL_Global::UnionLottoShowTip(dateBoxString.c_str(), VSDL_Point(currentXY.x + tipWidth, currentXY.y));
	}

	SPG_Rect(destSurf, currentXY.x + tipWidth, currentXY.y, currentXY.x + tipWidth * 2, currentXY.y + tipHeight, rgb.GetRGB32(destSurf));

	rgb = rgbNormal;
	currentXY.y += tipHeight;

	UL_Global::UnionLottoShowTip("期数:(例:16)", currentXY);

	if (selectedBox == RANGE_BOX){
		rgb = rgbSelected;
	}else{
		rgb = rgbNormal;
	}

	if (rangeBoxString.length() > 0){
		UL_Global::UnionLottoShowTip(rangeBoxString.c_str(), VSDL_Point(currentXY.x + tipWidth, currentXY.y));
	}

	SPG_Rect(destSurf, currentXY.x + tipWidth, currentXY.y, currentXY.x + tipWidth * 2, currentXY.y + tipHeight, rgb.GetRGB32(destSurf));

	rgb = rgbNormal;
	currentXY.y += tipHeight;

	//Draw input pad
	pad.Show(destSurf);
	//Draw spliting line
	historyY--;
	SPG_Line(destSurf, currentXY.x, historyY, destSurf->w, historyY, rgbNormal.GetRGB32(destSurf));

	//Show Range
	if (readyToGo){
		ULC_Serial *serial = ulgHistory->LookupRange(startSerialNo, nSerials);

		if (serial == NULL){
			UL_Global::UnionLottoShowTip("No such serial", VSDL_Point(STATISTIC_FINAL_START_X, historyY));
			return ;
		}

		ulgStat->Show(destSurf, SERIALS_PER_SCREEN, serial + serialOffset, false);

		ShowStatistic(destSurf, nSerials, serial);

	}
}

void ULUI_StatisticOut::ShowStatistic(SDL_Surface *destSurf, int nSerials, ULC_Serial *serials)
{
#define BALLS_PER_ROW	11
	VSDL_Point currentXY;
	ULC_BallFrequency tmp;
	list<ULC_BallFrequency>::iterator iter;
	ULC_PositionInfo *info;
	char msgBuffer[128] = {0};
	int w, h;
	int count = 0;
	VSDL_Text text;
	int tipStartX = (destSurf->w >> 1) + FIXED_GAP;
	VSDL_RGB rgbLine(100, 100, 100);

	text.SetFont(UL_Global::UnionLottoFont());
	text.SetText("0");
	text.GetTextSize(&w, &h);

	ulcStat.ParseSerials(nSerials, serials);

	currentXY.x = tipStartX;
	currentXY.y = STATISTIC_FINAL_START_Y + (EXIT + 2) * tipHeight;
	UL_Global::UnionLottoShowTip("出现的红球:", currentXY);
	currentXY.y += h;

	//Deal with red ones
	for (int i = 0; i < UL_RED_BALLS_COUNT; i++){
		info = ulcStat.GetOutRedInfo(i);

		sprintf(msgBuffer, "第%d个位置:", i + 1);
		currentXY.x = tipStartX;
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.x += w * 12;
		count = 0;

		for (iter = info->numberOrder.begin(); iter != info->numberOrder.end(); iter++){
			tmp = *iter;

			sprintf(msgBuffer, "%02d ", tmp.number);
			UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
			currentXY.x += w * 3;
			count++;

			if (count == BALLS_PER_ROW){
				count == 0;
				currentXY.x = tipStartX + w * 12;
				currentXY.y += h;
			}
		}

		currentXY.y += h;
	}

	currentXY.x = tipStartX;
	currentXY.y++;
	//Draw spliting line
	SPG_Line(destSurf, currentXY.x, currentXY.y, destSurf->w, currentXY.y, rgbLine.GetRGB32(destSurf));
	UL_Global::UnionLottoShowTip("红球概率(从小到大):", currentXY);
	currentXY.y += h;
	//Display rate order
	for (int i = 0; i < UL_RED_BALLS_COUNT; i++){
		info = ulcStat.GetOutRedInfo(i);

		sprintf(msgBuffer, "第%d个位置:", i + 1);
		currentXY.x = tipStartX;
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.x += w * 12;
		count = 0;

		for (iter = info->rateOrder.begin(); iter != info->rateOrder.end(); iter++){
			tmp = *iter;

			sprintf(msgBuffer, "%02d ", tmp.number);
			UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
			currentXY.x += w * 3;
			count++;

			if (count == BALLS_PER_ROW){
				count == 0;
				currentXY.x = tipStartX + w * 12;
				currentXY.y += h;
			}
		}

		currentXY.y += h;
	}


	currentXY.x = tipStartX;
	currentXY.y += h - 1;
	//Draw spliting line
	SPG_Line(destSurf, currentXY.x, currentXY.y, destSurf->w, currentXY.y, rgbLine.GetRGB32(destSurf));
	//Deal with blue one
	info = ulcStat.GetBlueInfo();	

	UL_Global::UnionLottoShowTip("出现的蓝球:", currentXY);
	currentXY.y += h;
	currentXY.x = tipStartX + w * 12;
	count = 0;

	for (iter = info->numberOrder.begin(); iter != info->numberOrder.end(); iter++){
		tmp = *iter;
		sprintf(msgBuffer, "%02d ", tmp.number);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.x += w * 3;
		count++;

		if (count == BALLS_PER_ROW){
			count == 0;
			currentXY.x = tipStartX + w * 12;
			currentXY.y += h;
		}
	}

	currentXY.x = tipStartX;
	currentXY.y += h - 1;
	//Draw spliting line
	SPG_Line(destSurf, currentXY.x, currentXY.y, destSurf->w, currentXY.y, rgbLine.GetRGB32(destSurf));
	UL_Global::UnionLottoShowTip("蓝球概率(从小到大):", currentXY);
	currentXY.x = tipStartX + w * 12;
	currentXY.y += h;
	count = 0;

	for (iter = info->rateOrder.begin(); iter != info->rateOrder.end(); iter++){
		tmp = *iter;
		sprintf(msgBuffer, "%02d ", tmp.number);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.x += w * 3;
		count++;

		if (count == BALLS_PER_ROW){
			count == 0;
			currentXY.x = tipStartX + w * 12;
			currentXY.y += h;
		}
	}
	
	//Draw rect
	currentXY.y += h - 1;
	SPG_Rect(destSurf, tipStartX, STATISTIC_FINAL_START_Y + (EXIT + 2) * tipHeight, destSurf->w, currentXY.y, rgbLine.GetRGB32(destSurf));

}

ULUI_StatisticOut *ULUI_StatisticOut::Instance()
{
	return &statOut;
}


void __HANDLE_EVENT ULUI_StatisticOut::OnKeyDown(SDLKey keysym, unsigned char *keyStates, void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	//Basic
	if (keyStates[SDLK_ESCAPE]){
		game->PopState();
	}

	//Special cases
	if (keyStates[SDLK_RETURN]){
		selectedMenu = OK;
		return ;
	}

	if (keyStates[SDLK_UP]){
		selectedMenu--;

		if (selectedMenu < 0){
			selectedMenu = 0;
		}

		return ;
	}

	if (keyStates[SDLK_DOWN]){
		selectedMenu++;

		if (selectedMenu > OK){
			selectedMenu = OK;
		}

		return ;
	}

	if (nSerials <= SERIALS_PER_SCREEN){
		serialOffset = 0;
	}else{
		if (keyStates[SDLK_PAGEUP]){
			serialOffset--;

			if (serialOffset < 0){
				serialOffset = 0;
			}
		}

		if (keyStates[SDLK_PAGEDOWN]){
			serialOffset++;

			if (serialOffset + SERIALS_PER_SCREEN >= nSerials){
				serialOffset = nSerials - SERIALS_PER_SCREEN;
			}
		}
	}

	pad.PushKeysym(keysym);
}

void __HANDLE_EVENT ULUI_StatisticOut::OnMouseMove(int button, unsigned char buttonState, int absX, int absY, int relX, int relY, void *arg)
{
	menus.UpdateMenuList(absX, absY);
	pad.UpdateStatus(absX, absY);
}

void __HANDLE_EVENT ULUI_StatisticOut::OnMouseDown(int button, unsigned char buttonState, int absX, int absY, void *arg)
{
	int i;
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		ULUI_Menu &menu = menus.GetMenu(i);

		if (menu.IsXYInRect(absX, absY)){
			selectedMenu = i;
			break;
		}
	}

	pad.OnMouseDown(absX, absY);

	//Special case for WHEEL
	if (nSerials <= SERIALS_PER_SCREEN){
		serialOffset = 0;
	}else{
		if (button == SDL_BUTTON_WHEELUP){
			serialOffset--;

			if (serialOffset < 0){
				serialOffset = 0;
			}
		}

		if (button == SDL_BUTTON_WHEELDOWN){
			serialOffset++;

			if (serialOffset + SERIALS_PER_SCREEN >= nSerials){
				serialOffset = nSerials - SERIALS_PER_SCREEN;
			}
		}
	}
}

void __HANDLE_EVENT ULUI_StatisticOut::OnQuit(void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	game->Quit();
}
